<?php

namespace CommonBundle\View;

use CommonBundle\Service\BaseService;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Swagger\Annotations as SWG;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Validator\Exception\ValidatorException;
use Symfony\Component\Workflow\Exception\ExceptionInterface;

trait WorkflowApiViewMixin
{
    // protected $workflow;

    /**
     * Todo list
     *
     * @Route("/todo", name="todo-list", methods={"GET"})
     * @SWG\Response(
     *     response=200,
     *     description="Todo list",
     * )
     * @SWG\Parameter(name="page", in="query", type="string")
     * @SWG\Parameter(name="limit", in="query", type="string")
     * @return Response
     */
    public function todoAction()
    {
        $service = $this->get($this->serviceClass);
        $entities = BaseService::listResultToCollection(
            $service->list(null, null, false)
        )->toArray();

        // TODO: this method will VERY SLOW when reached the large apply entry.
        $entities = array_filter($entities, function ($entity) {
            $workflow = $this->get($this->workflow);
            return count($workflow->getEnabledTransitions($entity));
        });

        return $this->Success($entities);
    }

    /**
     * List enabled transitions
     *
     * @Route("/{id}/transitions", name="available-transition", methods={"GET"})
     * @SWG\Response(
     *     response=200,
     *     description="List enabled transitions",
     * )
     * @param $id
     * @return Response
     */
    public function availableTransitionsAction($id)
    {
        $service = $this->get($this->serviceClass);
        $entity = $service->get(['id' => $id]);

        $workflow = $this->get($this->workflow);
        $transitions = $workflow->getEnabledTransitions($entity);

        return $this->Success($transitions);
    }

    /**
     * Do transition
     *
     * @Route("/{id}/do/{transition}", name="do-transition")
     * @Method("POST")
     * @SWG\Response(
     *     response=200,
     *     description="Do transition",
     * )
     * @param Request $request
     * @param $id
     * @param $transition
     * @return Response
     */
    public function doTransitionAction(Request $request, $id, $transition): Response
    {
        try {
            $service = $this->get($this->serviceClass);
            $entity = $service->get(['id' => $id]);
            $workflow = $this->get($this->workflow);

            if($workflow->can($entity, $transition)) {
                $content = json_decode($request->getContent(), true);
                $content['tempTransition'] = $transition;
                if($content) {
                    $service->update($entity, $content);
                }

                $workflow->apply($entity, $transition);
                $this->get('doctrine')->getManager()->flush();
            }
            else {
                throw new ValidatorException('Current transition cannot be applied.');
            }

        } catch (ExceptionInterface $e) {
            return $this->Warning($e->getMessage());
        }

        return $this->Success();
    }

    /**
     * Reset marking
     *
     * @Security("has_role('ROLE_ADMIN')")
     * @Route("/{id}/status-reset", name="reset-status")
     * @Method("PUT")
     * @SWG\Response(
     *     response=200,
     *     description="Reset marking",
     * )
     * @param $entity
     * @return RedirectResponse
     */
    public function resetMarkingAction($entity)
    {
        $entity->setStatus([]);
        $this->get('doctrine')->getManager()->flush();

        return $this->Success();
    }
}
